﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace GSPatEditor.Bitmaps
{
    class CV2File : GSPatEditor.Pat.Image
    {
        public static Pat.Image CreateCV2FromFile(string filename)
        {
            if (!File.Exists(filename))
            {
                return Pat.Image.Empty;
            }
            return new CV2File(filename);
        }

        private readonly bool usePalette;
        private Bitmap bitmap;

        public override Bitmap CreateBitmapWithPalette(Pat.Palette pal)
        {
            if (usePalette)
            {
                ApplyPalette(pal);
            }
            var ret = bitmap.Clone(new Rectangle(0, 0, bitmap.Width, bitmap.Height), PixelFormat.Format32bppArgb);
            return ret;
        }

        private CV2File(string filename)
        {
            using (FileStream f_in = File.OpenRead(filename))
            {
                byte[] header = new byte[1 + 4 + 4 + 4 + 4];
                f_in.Read(header, 0, header.Length);
                int width = BitConverter.ToInt32(header, 1);
                int height = BitConverter.ToInt32(header, 5);
                int stride = BitConverter.ToInt32(header, 9);

                this.usePalette = (header[0] == 8);

                if (usePalette)
                {
                    this.bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                    var data = this.bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
                    byte[] readBuffer = new byte[stride];
                    for (int i = 0; i < height; ++i)
                    {
                        f_in.Read(readBuffer, 0, stride);
                        Marshal.Copy(readBuffer, 0, data.Scan0 + data.Stride * i, width * 1);
                    }
                    this.bitmap.UnlockBits(data);
                }
                else
                {
                    this.bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
                    var data = this.bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                    byte[] readBuffer = new byte[4 * stride];
                    for (int j = 0; j < height; ++j)
                    {
                        //for (int i = 0; i < stride; ++i)
                        //{
                            //f_in.Read(readBuffer, 0, 4);
                            //var c = Color.FromArgb(readBuffer[3], readBuffer[2], readBuffer[1], readBuffer[0]); //bgra8888
                            //if (i < width)
                            //{
                            //    this.bitmap.SetPixel(i, j, c);
                            //}
                        //}
                        f_in.Read(readBuffer, 0, 4 * stride);
                        Marshal.Copy(readBuffer, 0, data.Scan0 + data.Stride * j, width * 4);
                    }
                    this.bitmap.UnlockBits(data);
                }
            }

            base.Width = this.bitmap.Width;
            base.Height = this.bitmap.Height;
        }

        private void ApplyPalette(Pat.Palette pal)
        {
            ColorPalette palette = bitmap.Palette;
            for (int i = 0; i < 256; ++i)
            {
                palette.Entries[i] = pal.GetColorFromIndex(i);
            }
            bitmap.Palette = palette;
        }
    }
}
